package org.spiderflow.core.exception;

import org.spiderflow.core.expression.parsing.Span;

/**
 * Exception thrown by all basis-template code via {@link org.spiderflow.core.expression.ExpressionError#error(String, Span)}. In case an error happens deep inside a
 * list of included templates, the {@link #getMessage()} method will return a condensed error message.
 *
 * @author zhaoshihao
 * @version 2021/11/9 15:22
 */
public class TemplateException extends SpiderException {
    private static final long serialVersionUID = 1L;
    private final Span location;
    private final String errorMessage;

    public TemplateException(String message, Span location) {
        super(message);
        this.errorMessage = message;
        this.location = location;
    }

    public TemplateException(String message, Span location, Throwable cause) {
        super(message, cause);
        this.errorMessage = message;
        this.location = location;
    }

    /**
     * Returns the location in the template at which the error happened.
     **/
    public Span getLocation() {
        return location;
    }

    @Override
    public String getMessage() {
        StringBuilder builder = new StringBuilder();

        if (getCause() == null || getCause() == this) {
            return super.getMessage();
        }

        builder.append(errorMessage, 0, errorMessage.indexOf('\n'));
        builder.append("\n");

        Throwable cause = getCause();
        while (cause != null && cause != this) {
            if (cause instanceof TemplateException) {
                TemplateException ex = (TemplateException) cause;
                if (ex.getCause() == null || ex.getCause() == ex) {
                    builder.append(ex.errorMessage);
                } else {
                    builder.append(ex.errorMessage, 0, ex.errorMessage.indexOf('\n'));
                }
                builder.append("\n");
            }
            cause = cause.getCause();
        }
        return builder.toString();
    }
}
